package server

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"

	lg "stock_ths/log"
	"strings"
)

var mux map[string]func(w http.ResponseWriter, r *http.Request)

// mux = make(map[string]func(http.ResponseWriter, *http.Request))

type MyHandler struct {
	// mux := make(map[string]func(http.ResponseWriter, *http.Request))
}

func initHandler() {
	mux = make(map[string]func(w http.ResponseWriter, r *http.Request))
	mux["/api/get/days"] = getDaysData
	mux["/api/get/breakthrough/curve"] = getBreakCurve
	mux["/api/get/times"] = getTimesData
}

func (lh *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// lg.ILogger.Println("ServeHTTP:", r.URL.Path)
	if r.Method != http.MethodPost && r.Method != http.MethodGet && r.Method != http.MethodOptions {
		body, err := getRequestBody(w, r)
		if err != nil {
			lg.ELogger.Println("getRequestBody:", err)
			return
		}
		// w.Write(w, string(body))
		cors(w, r)
		w.WriteHeader(http.StatusForbidden)
		w.Write(body)
		return
	}
	if r.Method == http.MethodOptions {
		cors(w, r)
		w.WriteHeader(http.StatusOK)
		// w.Write()
		return
	} else if r.Method == http.MethodPost || r.Method == http.MethodGet {
		if h, ok := mux[r.URL.Path]; ok {
			cors(w, r)
			h(w, r)
			return
		}
	}
	cors(w, r)
	w.WriteHeader(http.StatusForbidden)
}

func cors(w http.ResponseWriter, r *http.Request) {
	// w.Header().Set("Access-Control-Allow-Origin", "*")             //允许访问所有域
	// w.Header().Add("Access-Control-Allow-Headers", "Content-Type") //header的类型

	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
	w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, token")
	w.Header().Add("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
	w.Header().Add("Access-Control-Allow-Credentials", "true")
	// lg.ILogger.Println("cors header!", r.URL.Path)
}

func DefaultQuery(url *url.URL, key, defaultValue string) string {
	v := url.Query().Get(key)
	if len(v) == 0 {
		return defaultValue
	}

	return v
}

func QueryNum(url *url.URL, key string) (int, error) {
	v := url.Query().Get(key)
	if len(v) == 0 {
		return -1, nil
	}

	iv, err := strconv.Atoi(v)
	if err != nil {
		return -1, err
	}

	return iv, nil
}

func writeError(w http.ResponseWriter, r *http.Request, err error) {
	cors(w, r)
	w.WriteHeader(http.StatusBadRequest)
	w.Write([]byte(err.Error()))
}

func parseJsonBody(w http.ResponseWriter, r *http.Request, v interface{}) error {
	is_json := false
	for _, t := range r.Header["Content-Type"] {
		ct := strings.ToLower(t)
		if strings.Contains(ct, "application/json") {
			is_json = true
		}
	}

	body, err := getRequestBody(w, r)
	if err != nil {
		lg.ELogger.Println("getRequestBody:", err)
		return err
	}

	lg.ILogger.Println("body:", string(body))
	if is_json {
		err = parseJson(body, v)
		return err
	}

	return errors.New("not json")
}
func getRequestBody(w http.ResponseWriter, r *http.Request) ([]byte, error) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		// ud.ELogger.Println("read body error!")
		lg.ELogger.Println("read body error!")
		return body, err
	}
	return body, err
}
func parseJson(d []byte, v interface{}) error {
	err := json.Unmarshal(d, v)
	if err != nil {
		lg.ELogger.Println("parse json error:", err)
		lg.ELogger.Println("data:", string(d))
		return err
	}
	return nil
}

// // 解析请求头，并验证token
// func parseHeader(w http.ResponseWriter, r *http.Request) error {
// 	if len(r.Header) > 0 {
// 		for k, v := range r.Header {
// 			//    fmt.Printf("%s=%s\n", k, v[0])
// 			lg.ILogger.Println(k, "=", v[0])
// 			if strings.ToLower(k) == "token" {
// 				c, err := tokenSign(WuhanData{Token: v[0]})
// 				if err != nil {
// 					return err
// 				}
// 				if c.Code == 0 {
// 					return errors.New(c.Msg)
// 				} else if c.Code == 1 {
// 					return nil
// 				}
// 				break
// 			}
// 		}
// 	}

// 	return errors.New("no token")
// }
